#pragma once
#include "tcpLog.hpp"
#include "Task.hpp"
#include "ThreadPool.hpp"
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <cstring>
#include <strings.h>
#include <cstdio>
#define NUM 1024
enum
{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    LISTEN_ERR,
    FORK_ERR,
    WAIT_ERR
};
namespace Server
{
    void serverIo(int sockfd)
    {
        char buffer[1024];
        while (true)
        {
            // 由于tcp是面向字节流的，可以直接使用文件的接口
            ssize_t n = read(sockfd, buffer, sizeof(buffer) - 1);
            if (0 == n)
            {
                logMessage(NORMAL, "client quit, me too");
                break;
            }

            buffer[n] = 0;
            std::cout << "recv message: " << buffer << std::endl;

            std::string response = buffer;
            response += " server [echo]";
            // std::cin >> response;
    
            write(sockfd, response.c_str(), response.size());
        }

        close(sockfd);
    }
    using namespace std;
    class TcpServer;
    class ServerThreadData
    {
    public:
        ServerThreadData(TcpServer *self, int sock)
            : _self(self), _sock(sock)
        {
        }

    public:
        TcpServer *_self;
        int _sock;
    };
    class TcpServer
    {
        static const int gbacklog = 5;

    public:
        TcpServer(const uint16_t port)
            : _port(port), _listensock(-1)
        {
        }
        void initServer()
        {
            // 1.创建socket套接字对象
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock == -1)
            {
                logMessage(FATAL, "listen socket error");
                exit(SOCKET_ERR);
            }
            logMessage(NORMAL, "listen socket success sockfd: %d", _listensock);

            // 2.绑定ip和端口
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) != 0)
            {
                logMessage(FATAL, "bind error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL, "bind success");

            // 3.设置socket为监听状态
            if (listen(_listensock, gbacklog) < 0)
            {
                logMessage(FATAL, "listen error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL, "listen success");
            
            std::cout << "success" << std::endl;
            // version 3 多进程 信号忽略子进程的退出，让os回收子进程资源
            // signal(SIGCHLD, SIG_IGN);
        }
        void start()
        {
            // 4.初始化线程池
            ThreadPool<Task>::GetInstance()->run();
            logMessage(DEBUG, "create ThreadPool success");
            while (1)
            {
                // 接受远端连接
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int sockfd = accept(_listensock, (struct sockaddr *)&client, &len);
                std::cout << inet_ntoa(client.sin_addr) << std::endl;
                if (sockfd == -1)
                {
                    logMessage(ERROR, "accept error");
                    continue;
                }
                logMessage(NORMAL, "accept a new link success, get new sock: %d", sockfd);

                // 测试代码·
                logMessage(DEBUG, "accept error, next");
                logMessage(WARNING, "accept error, next");
                logMessage(FATAL, "accept error, next");
                logMessage(NORMAL, "accept error, next");

                logMessage(DEBUG, "accept error, next");
                logMessage(WARNING, "accept error, next");
                logMessage(FATAL, "accept error, next");
                logMessage(NORMAL, "accept error, next");

                logMessage(NORMAL, "accept a new link success, get new sock: %d", sockfd); // ?
                logMessage(DEBUG, "accept error, next");
                logMessage(WARNING, "accept error, next");
                logMessage(FATAL, "accept error, next");
                logMessage(NORMAL, "accept error, next");
                // version 1 单进程
                // serverIo(sockfd);
                // close(sockfd);  //很重要，通信结束后关闭文件描述符，避免文件描述符泄漏

                //version 2 多进程 孙子进程处理
                // pid_t id = fork();
                // if (id == 0) //子进程
                // {
                //     close(_listensock);
                //     if (fork() > 0)
                //         exit(0); //创造孙子进程，子进程先退出，孙子进程变成孤儿进程，由os领养，优雅但不高效
                //     serverIo(sockfd);
                //     close(sockfd);
                //     exit(0);
                // }
                // else if (id == -1)
                // {
                //     logMessage(FATAL, "fork error");
                //     exit(FORK_ERR);
                // }
                // close(sockfd);
                // pid_t ret = waitpid(id, nullptr, 0);
                // if (ret == -1)
                // {
                //     logMessage(FATAL, "waitpid error");
                //     exit(WAIT_ERR);
                // }
                // else if (ret > 0)
                // {
                //     // logMessage(NORMAL, "waitpid success");
                //     std::cout << "waitpid success" << std::endl;
                // }

                // version 4 多线程
                //  ServerThreadData *std = new ServerThreadData(this, sockfd);
                //  pthread_t tid;
                //  pthread_create(&tid, nullptr, startRoutine, (void *)std);

                // version 5 线程池技术
                ThreadPool<Task>::GetInstance()->push(Task(sockfd, serverIo));
            }
        }
        static void *startRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ServerThreadData *std = static_cast<ServerThreadData *>(args);
            serverIo(std->_sock);
            close(std->_sock);
            delete std;
            return nullptr;
        }

        ~TcpServer()
        {
        }

    private:
        int _listensock; // 不是用来通信的，是用来监听连接到来，获取新连接的
        uint16_t _port;
    };
}
